﻿using ImTools;

using NPOI.OpenXmlFormats.Dml.Diagram;

using PLCS.App.EquipmentManager;
using PLCS.App.Models;
using PLCS.App.Shared.Events;
using PLCS.App.Shared.Extensions;
using PLCS.App.Shared.Models;
using PLCS.App.Shared.Service;
using PLCS.App.Shared.Service.Dialog;
using PLCS.App.Shared.ViewModels;
using PLCS.Application.Contracts.EquipmentApp.Dtos;
using PLCS.Application.Contracts.PLCReadDataApp.Dtos;
using PLCS.Application.Contracts.StationApp.Dtos;
using PLCS.Client.IService.ConfigManager;
using PLCS.Client.IService.EquipmentManager;
using PLCS.Client.Service.ConfigManager;
using PLCS.Domain.Shared.Enums;
using PLCS.Domain.Shared.Stations;
using PLCS.Shared.Common.Constant;
using PLCS.Shared.Common.Extensions;
using PLCS.Shared.Common.Helper;

using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

using Volo.Abp.ObjectMapping;

namespace PLCS.App.ViewModels
{
    public class ModelingViewModel : BaseViewModel, INavigationAware
    {
        private double _cadW, _cadH;
        private ObservableCollection<ModelControl> _modelControls;
        private readonly IEventAggregator _eventAggregator;
        private readonly IHostDialogService _hostDialogService;
        private readonly IStationService _stationService;
        private readonly IEquipmentService _equipmentService;
        private readonly IPLCReadDataService _pLCReadDataService;
        private readonly CacheSettingService _cacheSettingService;
        private readonly IPLCConfigService _pLCConfigService;
        public readonly IEventAggregator aggregator;
        private readonly IObjectMapper<PLCSAppModule> _objectMapper;
        private DataTable table;

        public double CadW
        {
            get { return _cadW; }
            set
            {
                if (SetProperty(ref _cadW, value))
                {
                    Preview();
                }
            }
        }

        public double CadH
        {
            get { return _cadH; }
            set
            {
                if (SetProperty(ref _cadH, value))
                {
                    Preview();
                }
            }
        }

        public ObservableCollection<ModelControl> ModelControls
        {
            get { return _modelControls; }
            set { SetProperty(ref _modelControls, value); }
        }

        private string _searchKeyword;

        public string SearchKeyword
        {
            get => _searchKeyword;
            set
            {
                if (SetProperty(ref _searchKeyword, value))
                {
                    ModelControls = table.ToList<ModelControl>().WhereIf(!string.IsNullOrEmpty(value), x => x.SName.Contains(value)).ToObservable();
                }
            }
        }

        public DelegateCommand PreviewCommand { get; }
        public DelegateCommand<string> OpenAddDialogCommmand { get; }
        public DelegateCommand<ModelControl> OpenEditDialogCommmand { get; }
        public DelegateCommand SaveCommand { get; }
        public DelegateCommand<ModelControl> RemoveCommmand { get; }
        public DelegateCommand<ModelControl> CopyCommmand { get; }
        public DelegateCommand SyncDataCommand { get; }

        public ModelingViewModel(IEventAggregator eventAggregator,
                                 IHostDialogService hostDialogService,
                                 IStationService stationService,
                                 IEquipmentService equipmentService,
                                 IPLCReadDataService pLCReadDataService,
                                 CacheSettingService cacheSettingService,
                                 IPLCConfigService pLCConfigService,
                                 IEventAggregator aggregator,
                                 IObjectMapper<PLCSAppModule> objectMapper)
        {
            View = "建模界面";
            _eventAggregator = eventAggregator;
            _hostDialogService = hostDialogService;
            var tablewh = TableHelper.ExcelToTable(ModelConfigManager.ModelConfigPath, 1);
            CadW = double.Parse($"{tablewh.Rows[0]["CadW"]?.ToString()}");
            CadH = double.Parse($"{tablewh.Rows[0]["CadH"]?.ToString()}");

            table = TableHelper.ExcelToTable(ModelConfigManager.ModelConfigPath);
            ModelControls = table.ToList<ModelControl>().ToObservable();
            PreviewCommand = new DelegateCommand(Preview);
            OpenAddDialogCommmand = new DelegateCommand<string>(OpenAddDialog);
            OpenEditDialogCommmand = new DelegateCommand<ModelControl>(OpenEditDialog);
            SaveCommand = new DelegateCommand(Save);
            RemoveCommmand = new DelegateCommand<ModelControl>(Remove);
            SyncDataCommand = new DelegateCommand(SyncData);
            CopyCommmand = new DelegateCommand<ModelControl>(executeMethod: Copy);
            _eventAggregator.GetEvent<ModelControlEvent>().Subscribe(UpdateModelControls);
            _stationService = stationService;
            _equipmentService = equipmentService;
            _pLCReadDataService = pLCReadDataService;
            _cacheSettingService = cacheSettingService;
            _pLCConfigService = pLCConfigService;
            this.aggregator = aggregator;
            _objectMapper = objectMapper;
        }

        private void Copy(ModelControl control)
        {
            var copyControl = new ModelControl();
            Type controlType = typeof(ModelControl);
            PropertyInfo[] properties = controlType.GetProperties();

            foreach (PropertyInfo property in properties)
            {
                if (property.CanWrite)
                {
                    object value = property.GetValue(control);
                    property.SetValue(copyControl, value);
                }
            }

            copyControl.SName = control.SName + DateTime.Now.Ticks;
            copyControl.X = "100";
            copyControl.Y = "100";
            if (!ModelControls.Where(x => x.ControlType == copyControl.ControlType && x.SName == copyControl.SName).Any())
                ModelControls.Add(copyControl);

            Preview();
        }

        private async void SyncData()
        {
            try
            {
                UpdateLoading(true);
                var areaNo = _cacheSettingService.cacheSetting.AreaNo;
                var siteNo = _cacheSettingService.cacheSetting.SiteNo;
                var pdLineNo = _cacheSettingService.cacheSetting.PdLineNo;
                await _equipmentService.DeleteAllAsync();
                await _stationService.DeleteAllAsync();
                await _pLCReadDataService.DeleteAllAsync();
                var table = TableHelper.ExcelToTable(ModelConfigManager.ModelConfigPath);
                var modelControlConfigs = table.ToList<ModelControl>();
                var modelConfigs = modelControlConfigs.Where(x => !string.IsNullOrEmpty(x.EquipmentOrStation)).OrderBy(x =>
                {
                    if (x.EquipmentOrStation.Contains("Equipment"))
                        return 0;
                    else
                        return 1;
                }).ThenBy(x => int.Parse(KeepOnlyDigits(x.SName)));
                List<EquipmentEditDto> equipments = new List<EquipmentEditDto>();
                List<StationEditDto> stations = new List<StationEditDto>();
                List<PLCReadDataEditDto> pLCReadDatas = new List<PLCReadDataEditDto>();
                foreach (var item in modelConfigs)
                {
                    if (item.EquipmentOrStation.Contains("Equipment"))
                    {
                        var equipment = new EquipmentEditDto()
                        {
                            AreaNo = areaNo,
                            SiteNo = siteNo,
                            PdLineNo = pdLineNo,
                            EquName = $"{item.SName}",
                            EquName_Higher = $"{item.SName}",
                            EquName_Lower = $"{item.SName}",
                            EquNum = $"{item.SName}",
                            Plc_Index = int.Parse($"{item.Plc_Index}"),
                            PLCAddress = $"{item.PLCAddress}",
                            Rack = int.Parse($"{item.Rack}"),
                            Slot = int.Parse($"{item.Slot}"),
                            DbNumber = int.Parse($"{item.DbNumber}"),
                            ContainStationNos = string.IsNullOrEmpty(item.ContainStationNos) ? item.SName : item.ContainStationNos,
                            EquType = (EquipmentType)int.Parse(!string.IsNullOrEmpty(item.EquipmentType) ? item.EquipmentType : "0"),
                            InTrack = item.InTrack,
                        };
                        equipments.Add(equipment);

                        foreach (var stationNo in item.ContainStationNos.Split(ConstantChar.SplitChar))
                        {
                            var station = new StationEditDto()
                            {
                                AreaNo = areaNo,
                                SiteNo = siteNo,
                                PdLineNo = pdLineNo,
                                StaName = $"{stationNo}",
                                StaName_Higher = $"{stationNo}",
                                CanSend_EquNum = $"{item.CanSend}",
                                CanTake_EquNum = $"{item.CanTake}",
                                Capacity = int.Parse(string.IsNullOrEmpty(item.Capacity) ? "1" : item.Capacity.Trim()),
                                StaName_Lower = KeepOnlyDigits(stationNo),
                                StaNum = $"{stationNo}",
                                MultipleTrayType = item.MultipleTrayType,
                                Kind = item.Kind,
                            };
                            stations.Add(station);
                        }
                    }
                    else if (item.EquipmentOrStation.Contains("Station"))
                    {
                        var station = new StationEditDto()
                        {
                            AreaNo = areaNo,
                            SiteNo = siteNo,
                            PdLineNo = pdLineNo,
                            StaName = $"{item.SName}",
                            StaName_Higher = $"{item.SName}",
                            StaName_Lower = KeepOnlyDigits(item.SName),
                            StaNum = $"{item.SName}",
                            CanSend_EquNum = $"{item.CanSend}",
                            CanTake_EquNum = $"{item.CanTake}",
                            Capacity = int.Parse(string.IsNullOrEmpty(item.Capacity) ? "1" : item.Capacity.Trim()),
                            MultipleTrayType = item.MultipleTrayType,
                            Kind = $"{item.Kind}",
                            ParallelStation = $"{item.ParallelStation}",
                            StationType = (StationType)Enum.Parse(typeof(StationType), item.StationType),
                            Position = int.Parse(string.IsNullOrEmpty(item.Position) ? "0" : item.Position.Trim()),
                        };
                        stations.Add(station);
                    }
                }

                #region PLC读取

                var groups = modelConfigs.GroupBy(x => x.ReadPLCNo);
                foreach (var group in groups)
                {
                    if (string.IsNullOrEmpty(group.Key))
                        continue;
                    string plcNo = group.Key;

                    var plc = await _pLCConfigService.GetByNoAsync(plcNo);
                    if (plc == null)
                        await _pLCConfigService.CreateAsync(new Application.Contracts.PLCConfigApp.Dtos.PLCConfigEditDto()
                        {
                            IPAddress = ModelConfigManager.DefaultPLCAddress,
                            DBNumber = 600,
                            Length = 4000,
                            PLCName = plcNo,
                            PLCNo = plcNo,
                            Rack = 0,
                            Slot = 1,
                            Type = Domain.Shared.Enums.PLCType.西门子,
                            IsUse = Domain.Shared.Enums.YesNo.是,
                        });
                    int index = 0;
                    for (int i = 0; i < group.Count(); i++)
                    {
                        var item = group.ElementAt(i);
                        var equipmentOrStation = item.EquipmentOrStation;
                        if (equipmentOrStation == "Equipment")
                        {
                            var equName = $"{item.SName}";
                            var pLCReadData = new List<PLCReadDataEditDto>()
                       {
                       new PLCReadDataEditDto($"{equName}_Mode",plcNo,0+index, Domain.Shared.Enums.DataType.DINT,4,$"模式：1 单机 ；2 联机","T_Equipments","OnlineStatus","EquNum",equName),
                       new PLCReadDataEditDto($"{equName}_Status",plcNo,4+index, Domain.Shared.Enums.DataType.DINT,4,$"状态：1 空闲 ；2 忙碌 ；3  故障 ；4 暂停","EuipmentStatus","T_Equipments","Status","EquNum",equName),
                       new PLCReadDataEditDto($"{equName}_Current_Station",plcNo,8+index, Domain.Shared.Enums.DataType.DINT,4,$"当前工位","CurrentStation","T_Equipments","CurrentStation","EquNum",equName),
                       new PLCReadDataEditDto($"{equName}_Current_Pos",plcNo,12+index, Domain.Shared.Enums.DataType.DINT,4,$"当前坐标", "CurrentPos", "T_Equipments", "CurrentStation", "EquNum", equName),
                       new PLCReadDataEditDto($"{equName}_Current_Speed",plcNo,16+index, Domain.Shared.Enums.DataType.DINT,4,$"当前速度"),
                       new PLCReadDataEditDto($"{equName}_Current_TaskId",plcNo,20+index, Domain.Shared.Enums.DataType.DINT,4,$"当前任务ID","T_Equipments","CurrentTaskId","EquNum",equName),
                       new PLCReadDataEditDto($"{equName}_RunStatus",plcNo,24+index, Domain.Shared.Enums.DataType.DINT,4,$"运行状态"),
                       new PLCReadDataEditDto($"{equName}_ErrCode",plcNo,28+index, Domain.Shared.Enums.DataType.DINT,4,$"故障码","T_Equipments","ErrCode","EquNum",equName),
                       new PLCReadDataEditDto($"{equName}_Current_Lane",plcNo,32+index, Domain.Shared.Enums.DataType.DINT,4,$"当前巷道"),
                       new PLCReadDataEditDto($"{equName}_Current_Line",plcNo,36+index, Domain.Shared.Enums.DataType.DINT,4,$"当前排","OnCranePositionChanged",equName,"RG1"),
                       new PLCReadDataEditDto($"{equName}_Current_Column",plcNo,40+index, Domain.Shared.Enums.DataType.DINT,4,$"当前列"),
                       new PLCReadDataEditDto($"{equName}_Current_Layer",plcNo,44+index, Domain.Shared.Enums.DataType.DINT,4,$"当前层"),
                       new PLCReadDataEditDto($"{equName}_CompletionSignal",plcNo,96+index, Domain.Shared.Enums.DataType.DINT,4,$"完成信号","CompletionSignal","EquNum",equName),
                       };
                            index += ModelConfigManager.EquipmentIndexInterval;
                            pLCReadDatas.AddRange(pLCReadData);
                            var containStationNos = item.ContainStationNos.Split(ConstantChar.SplitChar);
                            for (int j = 0; j < containStationNos.Length; j++)
                            {
                                var staName = containStationNos[j].ToString();
                                var canSend = item.CanSend.Split(ConstantChar.SplitChar).Where(x => !string.IsNullOrEmpty(x)).OrderBy(x => KeepOnlyDigits(x)).ToArray();
                                var canTake = item.CanTake.Split(ConstantChar.SplitChar).Where(x => !string.IsNullOrEmpty(x)).OrderBy(x => KeepOnlyDigits(x)).ToArray();
                                var pLCReadDatason = new List<PLCReadDataEditDto>();

                                pLCReadDatason.Add(new PLCReadDataEditDto($"{staName}_TrayCount", plcNo, 0 + index, Domain.Shared.Enums.DataType.DINT, 4, "当前托盘数量", "T_Stations", "TrayCount", "StaNum", staName));
                                pLCReadDatason.Add(new PLCReadDataEditDto($"{staName}_EmptyFull", plcNo, 4 + index, Domain.Shared.Enums.DataType.DINT, 4, "空满位： 0 空； 1 满", "T_Stations", "HaveStatus", "StaNum", staName));
                                pLCReadDatason.Add(new PLCReadDataEditDto($"{staName}_ErrCode", plcNo, 8 + index, Domain.Shared.Enums.DataType.DINT, 4, "故障码", "T_Stations", "ErrCode", "StaNum", staName));
                                pLCReadDatason.Add(new PLCReadDataEditDto($"{staName}_Weight", plcNo, 12 + index, Domain.Shared.Enums.DataType.DINT, 4, "重量", "T_Stations", "Weight", "StaNum", staName));
                                pLCReadDatason.Add(new PLCReadDataEditDto($"{staName}_Trayno", plcNo, 16 + index, Domain.Shared.Enums.DataType.DINT, 4, "托盘号", "ScanAndStore", "", staName));
                                pLCReadDatason.Add(new PLCReadDataEditDto($"{staName}_MaterialType", plcNo, 20 + index, Domain.Shared.Enums.DataType.DINT, 4, "物料类型", "T_Stations", "CurrentMaterialSize", "StaNum", staName));
                                pLCReadDatason.Add(new PLCReadDataEditDto($"{staName}_ButtonSignal", plcNo, 24 + index, Domain.Shared.Enums.DataType.DINT, 4, "工位按钮信号"));

                                for (int k = 0; k < canTake.Length; k++)
                                {
                                    pLCReadDatason.Add(new PLCReadDataEditDto($"{staName}_Allow_Take_{canTake[k]}", plcNo, 28 + k * 4 + index, Domain.Shared.Enums.DataType.DINT, 4, "允许取", "UpdateCanOutAndInStatus", "", canTake[k], "CanOut", staName));
                                }

                                for (int k = 0; k < canSend.Length; k++)
                                {
                                    pLCReadDatason.Add(new PLCReadDataEditDto($"{staName}_Allow_Send_{canSend[k]}", plcNo, 28 + (canTake.Length + k) * 4 + index, Domain.Shared.Enums.DataType.DINT, 4, "允许送", "UpdateCanOutAndInStatus", "", canSend[k], "CanInSide", staName));
                                }
                                index += ModelConfigManager.EquipmentIndexInterval;
                                pLCReadDatas.AddRange(pLCReadDatason);
                            }
                        }
                        else if (equipmentOrStation == "Station")
                        {
                            // 如果是无广电货位，就不用存PLCReadData了
                            if (item.StationType == StationType.无光电货位.ToString())
                                continue;

                            var canSend = item.CanSend.Split(ConstantChar.SplitChar).Where(x => !string.IsNullOrEmpty(x)).OrderBy(x => KeepOnlyDigits(x)).ToArray();
                            var canTake = item.CanTake.Split(ConstantChar.SplitChar).Where(x => !string.IsNullOrEmpty(x)).OrderBy(x => KeepOnlyDigits(x)).ToArray();

                            var staName = item.SName;

                            var pLCReadData = new List<PLCReadDataEditDto>();

                            pLCReadData.Add(new PLCReadDataEditDto($"{staName}_TrayCount", plcNo, 0 + index, Domain.Shared.Enums.DataType.DINT, 4, "当前托盘数量", "T_Stations", "TrayCount", "StaNum", staName));
                            pLCReadData.Add(new PLCReadDataEditDto($"{staName}_EmptyFull", plcNo, 4 + index, Domain.Shared.Enums.DataType.DINT, 4, "空满位： 0 空； 1 满", "T_Stations", "HaveStatus", "StaNum", staName));
                            pLCReadData.Add(new PLCReadDataEditDto($"{staName}_ErrCode", plcNo, 8 + index, Domain.Shared.Enums.DataType.DINT, 4, "故障码", "T_Stations", "ErrCode", "StaNum", staName));
                            pLCReadData.Add(new PLCReadDataEditDto($"{staName}_Weight", plcNo, 12 + index, Domain.Shared.Enums.DataType.DINT, 4, "重量", "T_Stations", "Weight", "StaNum", staName));
                            pLCReadData.Add(new PLCReadDataEditDto($"{staName}_Trayno", plcNo, 16 + index, Domain.Shared.Enums.DataType.DINT, 4, "托盘号", "ScanAndStore", "", staName));
                            pLCReadData.Add(new PLCReadDataEditDto($"{staName}_MaterialType", plcNo, 20 + index, Domain.Shared.Enums.DataType.DINT, 4, "物料类型", "T_Stations", "CurrentMaterialSize", "StaNum", staName));
                            pLCReadData.Add(new PLCReadDataEditDto($"{staName}_ButtonSignal", plcNo, 24 + index, Domain.Shared.Enums.DataType.DINT, 4, "工位按钮信号"));

                            for (int j = 0; j < canTake.Length; j++)
                            {
                                pLCReadData.Add(new PLCReadDataEditDto($"{staName}_Allow_Take_{canTake[j]}", plcNo, 28 + j * 4 + index, Domain.Shared.Enums.DataType.DINT, 4, "允许取", "UpdateCanOutAndInStatus", "", canTake[j], "CanOut", staName));
                            }

                            for (int j = 0; j < canSend.Length; j++)
                            {
                                pLCReadData.Add(new PLCReadDataEditDto($"{staName}_Allow_Send_{canSend[j]}", plcNo, 28 + (canTake.Length + j) * 4 + index, Domain.Shared.Enums.DataType.DINT, 4, "允许送", "UpdateCanOutAndInStatus", "", canSend[j], "CanInSide", staName));
                            }

                            index += ModelConfigManager.EquipmentIndexInterval;
                            pLCReadDatas.AddRange(pLCReadData);
                        }
                    }
                }

                #endregion PLC读取

                #region 货位

                var rowGoodsModelConfigs = modelControlConfigs.Where(x => x.ControlType == "RowGoods").ToList();

                // 巷道
                var groupedRoadways = rowGoodsModelConfigs.GroupBy(x => x.Roadway).OrderBy(x => x.Key).ToList();
                for (int roadwayIndex = 0; roadwayIndex < groupedRoadways.Count; roadwayIndex++)
                {
                    var currentRoadwayConfigs = rowGoodsModelConfigs.Where(x => x.Roadway == groupedRoadways[roadwayIndex].Key).ToList();

                    // 排
                    for (int rowIndex = 0; rowIndex < currentRoadwayConfigs.Count; rowIndex++)
                    {
                        var currentRowConfig = currentRoadwayConfigs[rowIndex];
                        var tolalPosition = int.Parse(currentRowConfig.EndPosition) - int.Parse(currentRowConfig.StartPosition);

                        // 列
                        for (int columnIndex = 0; columnIndex < int.Parse(currentRowConfig.ColumnCount); columnIndex++)
                        {
                            // 层
                            for (int layerIndex = 0; layerIndex < int.Parse(currentRowConfig.LayerCount); layerIndex++)
                            {
                                var station = new StationEditDto()
                                {
                                    AreaNo = areaNo,
                                    SiteNo = siteNo,
                                    PdLineNo = pdLineNo,
                                    StaName = $"{currentRowConfig.Roadway}-{currentRowConfig.Row}-{columnIndex + 1}-{layerIndex + 1}",
                                    StaName_Higher = $"{currentRowConfig.Roadway}-{currentRowConfig.Row}-{columnIndex + 1}-{layerIndex + 1}",
                                    StaName_Lower = $"{currentRowConfig.Roadway}-{currentRowConfig.Row}-{columnIndex + 1}-{layerIndex + 1}",
                                    StaNum = $"{currentRowConfig.Roadway}-{currentRowConfig.Row}-{columnIndex + 1}-{layerIndex + 1}",
                                    CanSend_EquNum = $"{currentRowConfig.CanSend}",
                                    CanTake_EquNum = $"{currentRowConfig.CanTake}",
                                    Capacity = 1,
                                    Kind = $"{currentRowConfig.Kind}",
                                    ParallelStation = $"{currentRowConfig.ParallelStation}",
                                    StationType = Domain.Shared.Stations.StationType.无光电货位,
                                    MultipleTrayType = currentRowConfig.MultipleTrayType,
                                    Position = tolalPosition / int.Parse(currentRowConfig.ColumnCount) * columnIndex + int.Parse(currentRowConfig.StartPosition)
                                };

                                stations.Add(station);
                            }
                        }
                    }
                }

                #endregion 货位

                await _equipmentService.CreateEquipmentListAsync(equipments);
                await _stationService.CreateStationListAsync(stations);
                await _pLCReadDataService.CreatePLCReadDataListAsync(pLCReadDatas);

                ExportPLCReadData(pLCReadDatas, equipments);
                Log("保存", ModelControls);
                ShowMessage("同步成功");
            }
            catch (Exception ex)
            {
                ShowMessage($"同步失败，失败原因:{ex.Message}");
            }
            finally
            {
                UpdateLoading(false);
            }
        }

        private void ExportPLCReadData(List<PLCReadDataEditDto> pLCReadDatas, List<EquipmentEditDto> equipments)
        {
            // 读
            var document = _objectMapper.Map<List<PLCReadDataEditDto>, List<PlcInterFaceDocModel>>(pLCReadDatas);
            IEnumerable<IGrouping<string, PlcInterFaceDocModel>> readSheets = document.GroupBy(x => x.PLCConfigNo);
            int readCount = 0;
            foreach (var item in readSheets)
            {
                readCount++;

                var list = item.Select(g => g).ToList();
                TableHelper.TableToExcel(list.ToDataTable(), ModelConfigManager.PLCDocumentPath, "读" + item.Key, readCount);
            }

            // 写
            var writeSheets = equipments.OrderBy(x => x.Plc_Index).GroupBy(x => x.PLCAddress);
            int writeCount = 0;
            foreach (var item in writeSheets)
            {
                writeCount++;
                int index = 0;
                var list = new List<PlcInterFaceDocModel>();
                for (int i = 0; i < item.Count(); i++)
                {
                    var equipment = item.ElementAt(i);

                    #region 添加集合

                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_TaskId",
                        DataType = "DINT",
                        StartBit = 0 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "任务ID"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_TaskType",
                        DataType = "DINT",
                        StartBit = 4 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "任务类型 : ;1 工位行走； 2单取货；3 单放货；4取放货；5 单坐标行走；"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_TrayType",
                        DataType = "DINT",
                        StartBit = 8 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "托盘类型"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_TrayCount",
                        DataType = "DINT",
                        StartBit = 12 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "托盘数量 默认1"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_StartPos",
                        DataType = "DINT",
                        StartBit = 16 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "起始工位（对堆垛机此数据无用）"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_ToPos",
                        DataType = "DINT",
                        StartBit = 20 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "目标工位（对堆垛机此数据无用）"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_WorkingStation",
                        DataType = "DINT",
                        StartBit = 24 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "工作工位"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_FromLane",
                        DataType = "DINT",
                        StartBit = 28 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "堆垛机起始巷道"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_FromLine",
                        DataType = "DINT",
                        StartBit = 32 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "堆垛机起始排"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_FromColumn",
                        DataType = "DINT",
                        StartBit = 36 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "堆垛机起始列"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_FromLayer",
                        DataType = "DINT",
                        StartBit = 40 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "堆垛机起始层"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_ToLane",
                        DataType = "DINT",
                        StartBit = 44 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "堆垛机终点巷道"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_ToLine",
                        DataType = "DINT",
                        StartBit = 48 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "堆垛机终点排"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_ToColumn",
                        DataType = "DINT",
                        StartBit = 52 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "堆垛机终点列"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_ToLayer",
                        DataType = "DINT",
                        StartBit = 56 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "堆垛机终点层"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_MaterialType",
                        DataType = "DINT",
                        StartBit = 60 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "物料类型（物料长宽高）"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_MovePos",
                        DataType = "DINT",
                        StartBit = 64 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "移动坐标，单行走用"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_Confirm",
                        DataType = "DINT",
                        StartBit = 92 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "确认信号，收到PLC完成信号后写入"
                    });
                    list.Add(new PlcInterFaceDocModel()
                    {
                        PLCConfigNo = equipment.PLCAddress,
                        PLCReadDataNo = $"{equipment.EquNum}_StartSignal",
                        DataType = "DINT",
                        StartBit = 96 + index,
                        EndBit = 0,
                        Length = 4,
                        Remarks = "开始信号，PLC读到之后清除"
                    });

                    #endregion 添加集合

                    index += ModelConfigManager.EquipmentIndexInterval;
                }
                TableHelper.TableToExcel(list.ToDataTable(), ModelConfigManager.PLCDocumentPath, "写" + item.Key, readCount + writeCount);
            }
        }

        private static string KeepOnlyDigits(string input)
        {
            string pattern = "[^0-9]";
            return Regex.Replace(input, pattern, "").Trim();
        }

        private void Remove(ModelControl control)
        {
            ModelControls.Remove(control);
            Preview();
        }

        private void Save()
        {
            try
            {
                SaveFile();
                _eventAggregator.GetEvent<SaveEvent>().Publish();
                Log("保存", ModelControls);
                ShowMessage("保存成功。");
            }
            catch (Exception ex)
            {
                ShowMessage(ex.Message);
            }
        }

        private void SaveFile()
        {
            TableHelper.TableToExcel(ModelControls.ToDataTable(), ModelConfigManager.ModelConfigPath, "Sheet1", 0);
            var cads = new[]
            {
                      new{ CadH, CadW }
                }.ToList();

            TableHelper.TableToExcel(cads.ToDataTable(), ModelConfigManager.ModelConfigPath, "Sheet2", 1);
        }

        private void UpdateModelControls(ModelControl control)
        {
            if (!ModelControls.Where(x => x.ControlType == control.ControlType && x.SName == control.SName).Any())
            {
                ModelControls.Add(control);
            }
            Preview();
        }

        private async void OpenEditDialog(ModelControl control)
        {
            DialogParameters param = new DialogParameters
            {
                { "model", control }
            };
            await _hostDialogService.ShowDialogAsync($"Edit{control.ControlType}ControlDialogView", param);
        }

        private async void OpenAddDialog(string controlType)
        {
            await _hostDialogService.ShowDialogAsync($"Edit{controlType}ControlDialogView");
        }

        private void Preview()
        {
            _eventAggregator.GetEvent<ReloadEvent>().Publish();
        }

        #region INavigationAware

        /// <summary>
        /// 导航目标是否重新利用原来的对象
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <returns></returns>
        public bool IsNavigationTarget(NavigationContext navigationContext) => false;

        /// <summary>
        /// 导航发生变更时
        /// </summary>
        /// <param name="navigationContext"></param>
        public void OnNavigatedFrom(NavigationContext navigationContext)
        { }

        /// <summary>
        /// 导航到达时
        /// </summary>
        /// <param name="navigationContext"></param>
        public void OnNavigatedTo(NavigationContext navigationContext)
        { }

        #endregion INavigationAware

        #region 加载动画

        public void UpdateLoading(bool IsOpen)
        {
            aggregator.UpdateLoading(new UpdateModel()
            {
                IsOpen = IsOpen
            });
        }

        #endregion 加载动画
    }

    public class ControlModel
    {
        public string SName { get; set; }
        public string X { get; set; }
        public string Y { get; set; }
        public string Height { get; set; }
        public string Width { get; set; }
    }
}